﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;

namespace Assist
{
	public class AxisAssistFunc
	{
		public static List<Element> GetAllAxis(UIApplication uiApp)
		{
			List<Element> list = new List<Element>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(uiApp.ActiveUIDocument.Document);
			IList<Element> list2 = filteredElementCollector.OfClass(typeof(Grid)).ToElements();
			foreach (Element element in list2)
			{
				Grid grid = element as Grid;
				bool flag = grid != null;
				if (flag)
				{
					list.Add(grid);
				}
			}
			IList<Element> list3 = filteredElementCollector.OfClass(typeof(MultiSegmentGrid)).ToElements();
			foreach (Element element2 in list3)
			{
				MultiSegmentGrid multiSegmentGrid = element2 as MultiSegmentGrid;
				bool flag2 = multiSegmentGrid != null;
				if (flag2)
				{
					list.Add(multiSegmentGrid);
				}
			}
			return list;
		}

		public static List<Element> GetAxisByPoint(UIApplication uiApp, XYZ ptLoc)
		{
			List<Element> list = new List<Element>();
			List<Element> allAxis = AxisAssistFunc.GetAllAxis(uiApp);
			foreach (Element element in allAxis)
			{
				Grid grid = element as Grid;
				bool flag = grid != null;
				if (flag)
				{
					Curve curve = grid.Curve;
					XYZ closestPointTo = CurveAssistFunc.GetClosestPointTo(uiApp, curve, ptLoc, false);
					bool flag2 = closestPointTo == null;
					if (flag2)
					{
						continue;
					}
					bool flag3 = closestPointTo.DistanceTo(ptLoc) < 1E-06;
					if (flag3)
					{
						list.Add(grid);
					}
				}
				MultiSegmentGrid multiSegmentGrid = element as MultiSegmentGrid;
				bool flag4 = multiSegmentGrid != null;
				if (flag4)
				{
					List<Curve> locationCurves = AxisAssistFunc.GetLocationCurves(uiApp, uiApp.ActiveUIDocument.Document, multiSegmentGrid);
					foreach (Curve curve2 in locationCurves)
					{
						XYZ closestPointTo2 = CurveAssistFunc.GetClosestPointTo(uiApp, curve2, ptLoc, false);
						bool flag5 = closestPointTo2 == null;
						if (!flag5)
						{
							bool flag6 = closestPointTo2.DistanceTo(ptLoc) < 1E-06;
							if (flag6)
							{
								list.Add(multiSegmentGrid);
							}
						}
					}
				}
			}
			return list;
		}

		public static CurveLoop GetConCurvesLoop(UIApplication uiApp, List<Curve> arCurves)
		{
			CurveLoop curveLoop = new CurveLoop();
			XYZ pt = null;
			for (int i = 1; i < arCurves.Count; i++)
			{
				Curve curve = arCurves.ElementAt(i - 1);
				XYZ hyendPoint = curve.GetEndPoint(0);
				XYZ hyendPoint2 = curve.GetEndPoint(1);
				Curve curve2 = arCurves.ElementAt(i);
				XYZ hyendPoint3 = curve2.GetEndPoint(0);
				XYZ hyendPoint4 = curve2.GetEndPoint(1);
				bool flag = i == 1;
				if (flag)
				{
					bool flag2 = GeoUtil.IsPointEqual(hyendPoint2, hyendPoint3) || GeoUtil.IsPointEqual(hyendPoint2, hyendPoint4);
					if (flag2)
					{
						curveLoop.Append(curve);
						pt = hyendPoint2;
					}
					else
					{
						Curve curve3 = AxisAssistFunc.CalculateReverseCurve(uiApp, curve);
						curveLoop.Append(curve3);
						pt = hyendPoint;
					}
				}
				bool flag3 = GeoUtil.IsPointEqual(pt, hyendPoint3);
				if (flag3)
				{
					curveLoop.Append(curve2);
					pt = hyendPoint4;
				}
				else
				{
					bool flag4 = GeoUtil.IsPointEqual(pt, hyendPoint4);
					if (flag4)
					{
						Curve curve4 = AxisAssistFunc.CalculateReverseCurve(uiApp, curve2);
						curveLoop.Append(curve4);
						pt = hyendPoint3;
					}
				}
			}
			return curveLoop;
		}

		public static List<Curve> GetLocationCurves(UIApplication uiApp, Autodesk.Revit.DB.Document doc, MultiSegmentGrid grid)
		{
			List<Curve> list = new List<Curve>();
			ICollection<ElementId> gridIds = grid.GetGridIds();
			XYZ pt = null;
			for (int i = 1; i < gridIds.Count; i++)
			{
				Element element = RevitVersionFuncs.GetElement(doc, gridIds.ElementAt(i - 1));
				Grid grid2 = element as Grid;
				Curve curve = grid2.Curve;
				XYZ hyendPoint = curve.GetEndPoint(0);
				XYZ hyendPoint2 = curve.GetEndPoint(1);
				Element element2 = RevitVersionFuncs.GetElement(doc, gridIds.ElementAt(i));
				Grid grid3 = element2 as Grid;
				Curve curve2 = grid3.Curve;
				XYZ hyendPoint3 = curve2.GetEndPoint(0);
				XYZ hyendPoint4 = curve2.GetEndPoint(1);
				bool flag = i == 1;
				if (flag)
				{
					bool flag2 = GeoUtil.IsPointEqual(hyendPoint2, hyendPoint3) || GeoUtil.IsPointEqual(hyendPoint2, hyendPoint4);
					if (flag2)
					{
						list.Add(curve);
						pt = hyendPoint2;
					}
					else
					{
						Curve item = AxisAssistFunc.CalculateReverseCurve(uiApp, curve);
						list.Add(item);
						pt = hyendPoint;
					}
				}
				bool flag3 = GeoUtil.IsPointEqual(pt, hyendPoint3);
				if (flag3)
				{
					list.Add(curve2);
					pt = hyendPoint4;
				}
				else
				{
					bool flag4 = GeoUtil.IsPointEqual(pt, hyendPoint4);
					if (flag4)
					{
						Curve item2 = AxisAssistFunc.CalculateReverseCurve(uiApp, curve2);
						list.Add(item2);
						pt = hyendPoint3;
					}
				}
			}
			return list;
		}

		public static Curve CalculateReverseCurve(UIApplication uiApp, Curve curve)
		{
			Curve result = null;
			bool flag = curve.GetType() == typeof(Line);
			if (flag)
			{
				Line curve2 = curve as Line;
				result = YJKLineEx.YJKGetBound(curve2.GetEndPoint(1), curve2.GetEndPoint(0));
			}
			else
			{
				bool flag2 = curve.GetType() == typeof(Arc);
				if (flag2)
				{
					Arc arc = curve as Arc;
					XYZ center = arc.Center;
					XYZ hyendPoint = arc.GetEndPoint(0);
					XYZ hyendPoint2 = arc.GetEndPoint(1);
					XYZ normal = arc.Normal;
					XYZ radianPnt = AxisAssistFunc.CalculatMidPoint(hyendPoint, hyendPoint2, center, normal);
					result = uiApp.Application.CreatYJKArc(hyendPoint2, hyendPoint, radianPnt);
				}
			}
			return result;
		}

		public static XYZ CalculatMidPoint(XYZ ptStart, XYZ ptEnd, XYZ ptCenter, XYZ normal)
		{
			bool flag = normal.Z < 0.0;
			if (flag)
			{
				XYZ xyz = ptStart;
				ptStart = ptEnd;
				ptEnd = xyz;
			}
			XYZ xyz2 = ptStart - ptCenter;
			double length = xyz2.GetLength();
			xyz2 = xyz2.Normalize();
			double num = XYZ.BasisX.AngleOnPlaneTo(ptStart - ptCenter, XYZ.BasisZ);
			double num2 = XYZ.BasisX.AngleOnPlaneTo(ptEnd - ptCenter, XYZ.BasisZ);
			bool flag2 = num > num2;
			if (flag2)
			{
				num -= Math.PI*2;
			}
			double angle = (num2 - num) / 2.0;
			XYZ xyz3 = AxisAssistFunc.RotateTo(xyz2, angle, XYZ.BasisZ).Normalize();
			return ptCenter + xyz3 * length;
		}

		public static XYZ TransformPoint(XYZ point, Transform transform)
		{
			double x = point.X;
			double y = point.Y;
			double z = point.Z;
			XYZ xyz = transform.get_Basis(0);
			XYZ xyz2 = transform.get_Basis(1);
			XYZ xyz3 = transform.get_Basis(2);
			XYZ origin = transform.Origin;
			double num = x * xyz.X + y * xyz2.X + z * xyz3.X + origin.X;
			double num2 = x * xyz.Y + y * xyz2.Y + z * xyz3.Y + origin.Y;
			double num3 = x * xyz.Z + y * xyz2.Z + z * xyz3.Z + origin.Z;
			return new XYZ(num, num2, num3);
		}

		public static XYZ RotateTo(XYZ List, double angle, XYZ axis)
		{
			Transform transform = RevitVersionFuncs.CreateRotationAtPoint(axis, angle, new XYZ(0.0, 0.0, 0.0));
			return AxisAssistFunc.TransformPoint(List, transform);
		}
	}
}
